package quickAdd.client;

import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.XMLParser;

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;

/**
 * A dynamic grid of cells that adjust it's range to accomodate the cell data assigned to it.
 * CellData can return cells individually or as rows and has the capability to "shift" a range
 * of rows.
 * 
 * @author Pat Niemeyer nbk4pic
 * @created Mar 8, 2007
 */
public class CellData
{
    /**
     * Cells are strings right now.
     * Map a "row,col" composite string to a cell value
     **/
    Map/*<String,String>*/ cells = new HashMap();

    int minRow=-1, maxRow=-1, minCol=-1, maxCol=-1;

    public static CellData parse( Element feed )
    {
        return new CellData().parseCellFeed( feed );
    }

    public List/*<String>*/ getRow( int row ) {
        List rowValues = new ArrayList();
        for(int col=minCol; col<=maxCol; col++)
            rowValues.add( getCell( row, col ) );
        return rowValues;
    }

    public String getCell( int row, int col )
    {
        if ( row < minRow || row > maxRow || col < minCol || col > maxCol )
            return "-";
        //throw new IllegalArgumentException("invalid row,col: "+row+", "+col);
        return (String)cells.get( row + "," + col );
    }

    /**
     * Get the cell by a normalized view of the grid where effectively minRow, minCol = 0,0
     * @param row
     * @param col
     * @return
     */
    public String getCellNormalized( int row, int col ) {
        return getCell( row+minRow, col+minCol );
    }

    public void setCell( int row, int col, String value )
    {
        if ( row < 0 || col < 0 )
            throw new IllegalArgumentException( "row/col cannot be negative" );
        if ( row > maxRow || maxRow == -1 ) setMaxRow( row );
        if ( row < minRow || minRow == -1 ) setMinRow( row );
        if ( col > maxCol || maxCol == -1 ) setMaxCol( col );
        if ( col < minCol || minCol == -1 ) setMinCol( col );
        cells.put( row+","+col, value );
    }

    public CellData parseCellFeed( Element cellFeed )
    {
        NodeList entries = cellFeed.getElementsByTagName( "entry" );
        QuickAdd.out("entry nodelist length = "+entries.getLength() );
        for( int i=0; i<entries.getLength(); i++ ) {
            Element entry = (Element)entries.item( i );
            try {
                parseEntry( entry );
            } catch ( Exception e ) {
                QuickAdd.out("exception = "+e);
            }
        }
        return this;
    }

    private void parseEntry( Element entry ) {
        String value = DOMUtil.getSimpleElementText( entry, "content" );
        Element cell = DOMUtil.getFirstElement( entry, "gs:cell" );
        int row = Integer.parseInt( cell.getAttribute( "row" ) );
        int col = Integer.parseInt( cell.getAttribute( "col" ) );
        setCell( row, col, value );
    }

    public int getMinRow() { return minRow; }
    public void setMinRow( int minRow ) { this.minRow = minRow; }
    public int getMaxRow() { return maxRow; }
    public void setMaxRow( int maxRow ) { this.maxRow = maxRow; }
    public int getMinCol() { return minCol; }
    public void setMinCol( int minCol ) { this.minCol = minCol; }
    public int getMaxCol() { return maxCol; }
    public void setMaxCol( int maxCol ) { this.maxCol = maxCol; }
    public int getHeight() { return maxRow - minRow +1; }
    public int getWidth() { return maxCol - minCol +1; }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        for( int row=minRow; row<=maxRow; row++ ) {
            for( int col=minCol; col<=maxCol; col++ ) {
                sb.append( row + "," + col + "=" + getCell( row, col ) );
            }
            sb.append( "\n" );
        }
        sb.append( "width=" + getWidth() );
        sb.append( "height=" + getHeight() );
        return sb.toString();
    }

    public static void test() {
        Document doc = XMLParser.parse( data );
        Element feed = doc.getDocumentElement(); // feed
        CellData cd = new CellData();
        cd.parseCellFeed( feed );
        System.out.println( "cd = " + cd );
        QuickAdd.out( "cd = " + cd );
    }

    /* why doesn't this parse? */
    static String data =
        "<?xml version='1.0' encoding='UTF-8'?>"+
        "<feed xmlns=\"http://www.w3.org/2005/Atom\"\n" +
        "    xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\"\n" +
        "    xmlns:gs=\"http://schemas.google.com/spreadsheets/2006\">\n" +
        "    <id>\n" +
        "        http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full\n" +
        "    </id>\n" +
        "    <updated>2007-03-01T21:50:08.126Z</updated>\n" +
        "    <category scheme=\"http://schemas.google.com/spreadsheets/2006\"\n" +
        "        term=\"http://schemas.google.com/spreadsheets/2006#cell\"/>\n" +
        "    <title type=\"text\">Sheet1</title>\n" +
        "    <link rel=\"alternate\"\n" +
        "        type=\"text/html\"\n" +
        "        href=\"http://spreadsheets.google.com/ccc?key=o10922066485030349530.6403441927775707849\"/>\n" +
        "    <link rel=\"http://schemas.google.com/g/2005#feed\"\n" +
        "        type=\"application/atom+xml\"\n" +
        "        href=\"http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full\"/>\n" +
        "    <link rel=\"http://schemas.google.com/g/2005#post\"\n" +
        "        type=\"application/atom+xml\"\n" +
        "        href=\"http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full\"/>\n" +
        "    <link rel=\"self\"\n" +
        "        type=\"application/atom+xml\"\n" +
        "        href=\"http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full?min-row=1&#38;max-row=1\"/>\n" +
        "    <author>\n" +
        "        <name>patniemeyer</name>\n" +
        "        <email>patniemeyer@gmail.com</email>\n" +
        "    </author>\n" +
        "    <openSearch:startIndex>1</openSearch:startIndex>\n" +
        "    <gs:rowCount>4</gs:rowCount>\n" +
        "    <gs:colCount>3</gs:colCount>\n" +
        "    <entry>\n" +
        "        <id>\n" +
        "            http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full/R1C1\n" +
        "        </id>\n" +
        "        <updated>2007-03-01T21:50:08.126Z</updated>\n" +
        "        <category scheme=\"http://schemas.google.com/spreadsheets/2006\"\n" +
        "            term=\"http://schemas.google.com/spreadsheets/2006#cell\"/>\n" +
        "        <title type=\"text\">A1</title>\n" +
        "        <content type=\"text\">HeaderOne</content>\n" +
        "        <link rel=\"self\"\n" +
        "            type=\"application/atom+xml\"\n" +
        "            href=\"http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full/R1C1\"/>\n" +
        "        <link rel=\"edit\"\n" +
        "            type=\"application/atom+xml\"\n" +
        "            href=\"http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full/R1C1/tw28op\"/>\n" +
        "        <gs:cell row=\"1\"\n" +
        "            col=\"1\"\n" +
        "            inputvalue=\"HeaderOne\">HeaderOne\n" +
        "        </gs:cell>\n" +
        "    </entry>\n" +
        "    <entry>\n" +
        "        <id>\n" +
        "            http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full/R1C2\n" +
        "        </id>\n" +
        "        <updated>2007-03-01T21:50:08.126Z</updated>\n" +
        "        <category scheme=\"http://schemas.google.com/spreadsheets/2006\"\n" +
        "            term=\"http://schemas.google.com/spreadsheets/2006#cell\"/>\n" +
        "        <title type=\"text\">B1</title>\n" +
        "        <content type=\"text\">HeaderTwo</content>\n" +
        "        <link rel=\"self\"\n" +
        "            type=\"application/atom+xml\"\n" +
        "            href=\"http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full/R1C2\"/>\n" +
        "        <link rel=\"edit\"\n" +
        "            type=\"application/atom+xml\"\n" +
        "            href=\"http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full/R1C2/t23kgv\"/>\n" +
        "        <gs:cell row=\"1\"\n" +
        "            col=\"2\"\n" +
        "            inputvalue=\"HeaderTwo\">HeaderTwo\n" +
        "        </gs:cell>\n" +
        "    </entry>\n" +
        "    <entry>\n" +
        "        <id>\n" +
        "            http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full/R1C3\n" +
        "        </id>\n" +
        "        <updated>2007-03-01T21:50:08.126Z</updated>\n" +
        "        <category scheme=\"http://schemas.google.com/spreadsheets/2006\"\n" +
        "            term=\"http://schemas.google.com/spreadsheets/2006#cell\"/>\n" +
        "        <title type=\"text\">C1</title>\n" +
        "        <content type=\"text\">HeaderThree</content>\n" +
        "        <link rel=\"self\"\n" +
        "            type=\"application/atom+xml\"\n" +
        "            href=\"http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full/R1C3\"/>\n" +
        "        <link rel=\"edit\"\n" +
        "            type=\"application/atom+xml\"\n" +
        "            href=\"http://spreadsheets.google.com/feeds/cells/o10922066485030349530.6403441927775707849/od6/private/full/R1C3/br8g6p\"/>\n" +
        "        <gs:cell row=\"1\"\n" +
        "            col=\"3\"\n" +
        "            inputvalue=\"HeaderThree\">HeaderThree\n" +
        "        </gs:cell>\n" +
        "    </entry>\n" +
        "</feed>\n";
}
